#include<iostream>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
//-------------------1. 验证SIG_CHID信号 子进程退出时会向父进程发送----------------------
void handler(int sig)
{
    std::cout<<"child quit,father get a signo"<<std::endl;
}
//-------------------2.将对子进程回收的方法放在信号处理函数中
//v1----问题当有多个子进程同时退出时，同时发出SIGCHLD信号,父进程位图可能只修改了一个，只会处理一个
// void cleanupchild(int sig)
// {
//     if(sig == SIGCHLD)
//     {
//          pid_t rid = waitpid(-1,nullptr,0);
//          if(rid > 0)
//          {
//             std::cout<<"wait child success: "<<rid <<std::endl;
//          }
//     }
//     std::cout<<"wait sub done "<<std::endl;
// }


//v2 ----------处理有多个进程同时退出情况---------------------------------
// void cleanupchild(int sig)
// {
//     if(sig == SIGCHLD)
//     {
//         while(true)
//         {
//             pid_t rid = waitpid(-1,nullptr,0);//-1 表示回收任意一个子进程
//             if(rid > 0)
//             {
//                 std::cout<<"wait child success: "<<rid <<std::endl;
//             }
//             else if(rid <= 0) break;
//         }
//     }
//     std::cout<<"wait sub done "<<std::endl;
// }

//v3 ----------处理当有50个进车退出50个进程没有退出情况
void cleanupchild(int sig)
{
    if(sig == SIGCHLD)
    {
        while(true)
        {
            pid_t rid = waitpid(-1,nullptr,WNOHANG);//-1 表示回收任意一个子进程,WNOHANG表示非阻塞式等待，等待失败不会阻塞，
            if(rid > 0)
            {
                std::cout<<"wait child success: "<<rid <<std::endl;
            }
            else if(rid <= 0) break;
        }
    }
    std::cout<<"wait sub done "<<std::endl;
}
int main()
{
    signal(SIGCHLD,SIG_IGN);
    for(int i = 1;i<=100;i++)
    {
        pid_t id = fork();
        if(id == 0)
        {
            //child process 
            int cnt = 5;
            while(cnt--)
            {
                std::cout<<" I am child process :"<<getpid()<<std::endl;
                //sleep(1);
            }
            std::cout<<"child process died"<<std::endl;
            exit(0);
        }
    }
    //father
    while(true) sleep(1);
    return 0;
}




//---函数被执行流重复进入了导致产生了问题：该函数我们叫做不可重入函数 否则：可重入函数 。----我们使用的大部分函数都时不可重入函数



//--------------------1. 验证信号其他捕捉方法--------------------
//--------------------2. 信号处理函数被调用时，内核会自动将当前信号加入进程的信号屏蔽字--------------------
//--------------------2. 当处理完对应的信号，该信号默认会从信号屏蔽字中进行移除--------------------
//----不想让信号，嵌套式进行捕捉处理
//在调用信号处理函数时，除了当前信号被自动屏蔽外，还希望自动屏蔽另外的一些信号，则用sa_mask字段说明

// void Print(sigset_t pending)
// {
//     for(int signo = 31;signo >=1;signo--)
//     {
//         if(sigismember(&pending,signo))
//         {
//             std::cout<<"1";
//         }
//         else
//         std::cout<<"0";
//     }
//     std::cout<<"\n";
// }
// void handler(int signo)
// {
//     std::cout<<"signo : "<<signo<<std::endl;
//     //不断获取当前进程的pending信号集并打印
//     sigset_t pending;
//     sigemptyset(&pending);
//     while(true)
//     {
//         sigpending(&pending);
//         Print(pending);
//     }

// }
// int main()
// {
//     struct sigaction act,old_act;
//     act.sa_handler = handler;
//     act.sa_flags = 0;
//     sigemptyset(&act.sa_mask);
//     sigaddset(&act.sa_mask,3);
//     sigaddset(&act.sa_mask,4);
//     sigaddset(&act.sa_mask,5);
//     sigaction(2,&act,&old_act);
//     while(true) sleep(1);
//     return 0;
// }